﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Mogre;

namespace ProjetInfoMogre
{
	public class Ogre : Entite
	{
		private bool porteCube;
		private Node monCube;
		private float mWalkSpeedRapide;
		private float mWalkSpeedNormale; 

		
		public bool connaitZonePierre=false;
		public Vector3 zonePierre;

		protected static int ajoutCubes=105; 

		public Ogre(SceneManager mSceneMgr, Vector3 Vposition, Monde monde)
			: base(mSceneMgr, Vposition, monde)
        {
            //Création de l'entité Robot
            entite = mSceneMgr.CreateEntity(name, "ogrehead.mesh");

            //Attache du robot à son noeud
            Noeud = mSceneMgr.RootSceneNode.CreateChildSceneNode(name + "Node", Vposition);
            Noeud.AttachObject(entite);

            // donne une première destination à l'ogre
            mDestination = new Vector3(random.Next(1500), 22, random.Next(1500));
            mDirection = mDestination - Noeud.Position;
            mDistanceRestante = mDirection.Normalise();

			porteCube = false;

			mWalkSpeedRapide = mWalkSpeed*2;
			mWalkSpeedNormale = mWalkSpeed;
        }

		public override void vit(float time)
		{
			communication();
			detectionRobots();
			if (porteCube)
			{
				if (mDistanceRestante <= 10f)
				{
					deposeCube();
				}
				else
				{
					this.walk(time);
				}
			}
			else
			{
				this.detection();
				this.walk(time);
			}
		}

        

		#region Actions de l'ogre

		public override void walk(float time) // vers une destination
		{
			if (!mWalking) // si l'ogre ne marhe pas encore
			{
				mWalking = true;
			}
			else //si l'ogre marche
			{
				if (mDistanceRestante > 0.0f)// si il n'est pas arrivé a sa destination
				{
					float distanceParcouru = mWalkSpeed * time; // le distance que l'ogre vient de parcourir est sa vitesse*le temps pendant lequel il veint de marcher

					//depalcement
					Noeud.Translate(mDirection * distanceParcouru);

					// on met a jour la distance qu'il lui reste a parcourir pour atteindre sa destination
					mDistanceRestante -= distanceParcouru;

					// Rotation 
					Vector3 src = Noeud.Orientation * Vector3.UNIT_X;
					if ((1.0f + src.DotProduct(mDirection)) < 0.0001f)
					{
						Noeud.Yaw(180.0f);
					}
					else
					{
						Quaternion quat = src.GetRotationTo(mDirection);
						Noeud.Rotate(quat);
						Noeud.Yaw(Mogre.Math.HALF_PI); // Rotation de la tête pour qu'elle regarde dans la direction où elle se dirige 
					}
				}
				else if (!porteCube)
				{
					if (!connaitZonePierre)
					{
						mDestination = new Vector3(random.Next(-1500, 1500), 22, random.Next(-1500, 1500));
					}
					else
					{
						int xMin = (int)zonePierre.x - 400;
						int zMax = (int)zonePierre.z + 400;
						mDestination = new Vector3(random.Next(xMin, 1450), 22, random.Next(-1450, zMax));
					}
					mDirection = mDestination - Noeud.Position;
					mDistanceRestante = mDirection.Normalise();
				}

			}
		}
		public override void detection() // des blocs
		{
			foreach (Node cube in monde.Cubes)
			{
				Vector3 distance = cube.Position - this.Noeud.Position;
				float distanceF = distance.Normalise();
				if (distanceF <= 100f)
				{
					connaitZonePierre = true;
					zonePierre = cube.Position;

					cube.Parent.RemoveChild(cube);
					this.Noeud.AddChild(cube);
					cube.Position = new Vector3(0, -6, 40);
					porteCube = true;
					monCube = cube;
					monde.Cubes.Remove(monCube);

					// Destination de la statue 
					mDestination = new Vector3(-1000, 22, 1000);
					mDirection = mDestination - Noeud.Position;
					mDistanceRestante = mDirection.Normalise();
					break;
				}
			}
		}
		public void communication()
		{
			if (this.connaitZonePierre)
			{
				foreach (Ogre ogre in monde.Ogres)
				{
					Vector3 distance = ogre.Noeud.Position - this.Noeud.Position;
					float distanceF = distance.Normalise();
					if (distanceF <= 200f)
					{
						// passe le message de la zone ou sont les pierres
						if (!ogre.connaitZonePierre)
						{
							ogre.zonePierre = this.zonePierre;
							ogre.connaitZonePierre = true;
							ogre.mDistanceRestante = 0f;
						}

					}
				}
			}
		}
		public void deposeCube()
		{
			monCube.Parent.RemoveChild(monCube);
			porteCube = false;

			//fait grossir la statue
			monde.tailleStatue++;
			float coeffMultiplicateur = (float)ajoutCubes / 100 ;
			float coeffReducteur= 1f / coeffMultiplicateur;
			//remet a la taille de départ
			monde.statueOgreNode.Scale(new Vector3(coeffReducteur, coeffReducteur, coeffReducteur));
			ajoutCubes+=5;
			coeffMultiplicateur = (float)ajoutCubes / 100;
			//regrossit avec le nouveau coef plus eleve
			monde.statueOgreNode.Scale(new Vector3(coeffMultiplicateur, coeffMultiplicateur, coeffMultiplicateur));
   			// se replace a la bonne hauteur
			float tailleDemieStatue = monde.statueOgre.BoundingBox.HalfSize.y*45*coeffMultiplicateur;
			monde.statueOgreNode.Translate(new Vector3(0, -monde.statueOgreNode.Position.y, 0));
			monde.statueOgreNode.Translate(new Vector3(0, tailleDemieStatue, 0));
						
			//repart
			int xMin = (int)zonePierre.x - 400;
			int zMax = (int)zonePierre.z + 400;
			mDestination = new Vector3(random.Next(xMin, 1450), 22, random.Next(-1450, zMax));
			mDirection = mDestination - Noeud.Position;
			mDistanceRestante = mDirection.Normalise();

		}
		public void detectionRobots()
		{
			// parcourir tous la liste des robots
			//si la distance avec un robot est inf au perimetre de detection
			// augmente sa vitesse

			foreach (Entite robot in monde.Robots)
			{
				Vector3 distance = robot.Noeud.Position - this.Noeud.Position;
				float distanceF = distance.Normalise();
				if (distanceF <= 150f)
				{
					mWalkSpeed = mWalkSpeedRapide;
					break;
				}
				else
				{
					mWalkSpeed = mWalkSpeedNormale;
				}
			}
		}

		#endregion



		#region Methodes annexes

		public bool PorteCube
        {
            get { return porteCube; }
            set { porteCube = value; }
        }
        public Node MonCube
        {
            get { return monCube; }
            set { monCube = value; }
		}

		#endregion


	}
}
